package lazy_save

import (
	"sync"
	"sync/atomic"
	"time"

	"xgame.go_server/comm/log"
)

// 延迟保存记录字典,
// key = GetLsoId(), val = lazySaveRecord
var innerMap = &sync.Map{}

// 是否已经启动
var started int32 = 0

//
// SaveOrUpdate 保存或更新
func SaveOrUpdate(newObj LazySaveObj) {
	if nil == newObj {
		return
	}

	log.Info(
		"记录延迟保存数据, lsoId = %+v",
		newObj.GetLsoId(),
	)

	currRecord, _ := innerMap.Load(newObj.GetLsoId())

	if nil != currRecord {
		// 修改最后更新时间
		currRecord.(*lazySaveRecord).lastUpdateTime = time.Now().UnixMilli()
		return
	}

	newRecord := &lazySaveRecord{
		objRef:         newObj,
		lastUpdateTime: time.Now().UnixMilli(),
	}

	innerMap.Store(newObj.GetLsoId(), newRecord)

	if atomic.CompareAndSwapInt32(&started, 0, 1) {
		go startLazySave()
	}
}

// 开始保存
func startLazySave() {
	go func() {
		for {
			// 先休息 1 秒
			time.Sleep(heartbeatTime)

			nowTime := time.Now().UnixMilli()
			deleteLsoIdArray := make([]string, 64)

			innerMap.Range(func(key, val interface{}) bool {
				if nil == key {
					return true
				}

				if nil == val {
					deleteLsoIdArray = append(deleteLsoIdArray, key.(string))
					return true
				}

				currRecord := val.(*lazySaveRecord)

				if nil == currRecord.objRef {
					deleteLsoIdArray = append(deleteLsoIdArray, key.(string))
					return true
				}

				if nowTime-currRecord.lastUpdateTime < steadyTime.Milliseconds() {
					// 如果时间差小于 60 秒
					// 不进行保存
					return true
				}

				log.Info(
					"执行延迟保存, lsoId = %+v",
					currRecord.objRef.GetLsoId(),
				)

				func() {
					defer func() { // 类似于 try
						if err := recover(); nil != err { // 类似于 catch
							log.Error("发生异常, %+v", err)
						}
					}()

					currRecord.objRef.SaveOrUpdate()
					deleteLsoIdArray = append(deleteLsoIdArray, currRecord.objRef.GetLsoId())
				}()

				return true
			})

			for _, lsoId := range deleteLsoIdArray {
				innerMap.Delete(lsoId)
			}
		}
	}()
}
